package designPatterns.com.course_design.scrapy.spider;

import designPatterns.com.course_design.scrapy.Engine;
import designPatterns.com.course_design.scrapy.http.request.Request;
import designPatterns.com.course_design.scrapy.http.response.Response;
import designPatterns.com.course_design.scrapy.logger.Log;
import designPatterns.com.course_design.scrapy.util.LogInjection;

import java.util.Queue;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

import static designPatterns.com.course_design.scrapy.util.ThreadSleep.sleepSeconds;

/**
 * @projectName DesignPattern
 * @className study.scrapy.Spider
 * @description
 */

public abstract class Spider extends ReentrantLock implements Runnable, RequestHandler {
    static int responseNum = 10;
    protected Engine engine;
    protected Queue<Response> responseQueue = new LinkedBlockingDeque<>();

    @LogInjection
    protected Log log;
    private final Condition condition = this.newCondition();

    public boolean isEmpty(){return responseQueue.isEmpty();}
    public void signalCondition() {
        this.condition.signalAll();
    }

    public void setEngine(Engine engine) {
        this.engine = engine;
    }

    public synchronized boolean signal() {
        this.lock();
        //队列为空，且正在等待
        boolean flag = !(this.getWaitQueueLength(condition) > 0 && this.responseQueue.isEmpty());
        this.unlock();
        return flag;
    }

    public void addResponse(Response response) {
        log.info("spider 接收到 response : " + response.getUrl() + " +body : " + response.getBody());
        this.responseQueue.add(response);
    }

    public void run() {
        //轮询，解析页面，并提交请求到引擎的request中
        while (this.engine.isRunning()) {
            this.lock();
            try {
                while (this.responseQueue.isEmpty() && this.engine.isRunning()) {
                    //优化，没事不占用时间片
                    condition.await();
                }
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            } finally {
                this.unlock();
            }
            //如果引擎关闭则退出，结束线程
            if (engine.getCurrentState() == Engine.END)
                break;
            //接收引擎发来的响应
            Response response = this.responseQueue.poll();
            log.debug("分析页面:" + response.getUrl());
            /*此代码可以让异步IO模型更明显*/
            sleepSeconds(1);
            //解析页面
            /*---------------此处使用用户自定义的页面解析函数-------------- */
            //调用模板方法---解析页面
            parseResponse(response);
        }
        System.out.println("=====================END OF SPIDER========================");
    }

    public abstract void parseResponse(Response response);

    //该层的职责仅仅是将解析出的request传递到下一层
    @Override
    public void push(Request request) {
        if (nextHandler != null) {
            nextHandler.push(request);
        }
    }

    private RequestHandler nextHandler;

    @Override
    public void setNextHandler(RequestHandler handler) {
        this.nextHandler = handler;
    }
}
